package pr2.mutacion;

import java.util.ArrayList;

import pr2.cromosoma.Cromosoma;
import pr2.cromosoma.CromosomaPVC;

public class MutacionHeuristica implements
		EstrategiaMutacion<CromosomaPVC> {

	private int numMutaciones;

	public MutacionHeuristica(int numMutaciones) {
		this.numMutaciones = numMutaciones;
	}

	@Override
	public void muta(CromosomaPVC cromosoma, double prob) {

		double probabilidad = Math.random();
		Integer pos = 0;
		ArrayList<Integer> posCiudades, ciudades;
		ArrayList<String> perms;
		double punt, mejorPunt = Double.MAX_VALUE;
		Cromosoma<CromosomaPVC> cromosomaAux;

		if (probabilidad <= prob) {
						
			posCiudades = new ArrayList<Integer>();
			ciudades = new ArrayList<Integer>();
			
			//Calculo las ciudades a permutar
			for (int i = 0; i < numMutaciones; i++) {
				while (posCiudades.contains(pos)) {
					pos = new Double(Math.random()
							* cromosoma.getFenotipo().size()).intValue();
				}
				posCiudades.add(pos);
				ciudades.add(cromosoma.getFenotipo().get(pos));
			}
			
			
			perms = new ArrayList<String>();

			//Calculo las posibles permutaciones
			calculaPermutaciones(perms, "", ciudades);
			
			cromosomaAux = cromosoma.clone();

			for (String perm : perms) {
				String[] permutacion = perm.split(";");

				for (int i = 0; i < numMutaciones; i++) {
					cromosomaAux.getFenotipo().set(posCiudades.get(i),
							Integer.parseInt(permutacion[i]));
				}
				
				punt = cromosomaAux.evalua();
				
				//Me quedo con la mejor permutacion
				if (punt < mejorPunt) {
					mejorPunt = punt;
					for (int i = 0; i < cromosoma.getFenotipo().size(); i++)
						cromosoma.getFenotipo().set(i, cromosomaAux.getFenotipo().get(i));
				}
			}

		}

	}

	private void calculaPermutaciones(ArrayList<String> perms, String tupla,
			ArrayList<Integer> conjunto) {
		if (conjunto.size() == 1) {
			tupla += ";" + conjunto.get(0).toString();
			perms.add(tupla);
			tupla = "";
		}
		for (int i = 0; i < conjunto.size(); i++) {
			Integer b = conjunto.remove(i);
			calculaPermutaciones(perms, (tupla.equals("") ? b.toString()
					: tupla + ";" + b), conjunto);
			conjunto.add(i, b);
		}
	}

}
